#include "wn_protocol.h"
#include "wn_crc.h"
#include <string.h>
#include "../emu_common.h"
#include "wn_uart.h"
#include "wn_device.h"
extern serial_t g_wn_serial;
int emupacket_device_basic(uint8_t addrID,uint8_t fcode,uint8_t*outmsg)
{
    outmsg[0]=0x68;
    outmsg[1]=0x00;
    outmsg[2]=addrID;
    outmsg[3]=fcode;
    return 4;
}

int emupacket_read_regs(uint8_t addId,uint16_t startReg,uint16_t regNum,uint8_t*outmsg)
{
    unsigned char msg[MGS_LEN_MAX];
    int num = 0;
    memset(msg,0,MGS_LEN_MAX);
    num = emupacket_device_basic(addId,FC_READ_REGS,msg);
    msg[num++]=startReg >>8;
    msg[num++]=startReg & 0xFF;
    msg[num++]=regNum >>8;
    msg[num++]=regNum & 0xFF;
    uint16_t crc_sum = modbus_crc16(msg,num);
    msg[num++] = crc_sum & 0xFF;
    msg[num++] = crc_sum >> 8;
    memcpy(outmsg,msg,num);
    return num;

}
//0x06
int emupacket_write_single_reg(uint16_t reg,uint16_t value,uint8_t*outmsg)
{
    unsigned char msg[MGS_LEN_MAX];
    int num = 0;
    memset(msg,0,MGS_LEN_MAX);
    num = emupacket_device_basic(1,FC_WRITE_REG,msg);
    msg[num++]=reg>>8;
    msg[num++]=reg&0xFF;
    msg[num++]=value>>8;
    msg[num++]=value&0xFF;
    uint16_t crc_sum = modbus_crc16(msg,num);
    msg[num++] = crc_sum & 0xFF;
    msg[num++] = crc_sum >> 8;
    memcpy(outmsg,msg,num);
    return EMU_SUCCESS;
    return EMU_SUCCESS;
}

//0x10
int emupacket_write_muti_reg(uint16_t reg,uint16_t value,uint8_t*outmsg)
{
    unsigned char msg[MGS_LEN_MAX];
    int num = 0;
    memset(msg,0,MGS_LEN_MAX);
    num = emupacket_device_basic(1,FC_WRITE_REGS,msg);
    msg[num++]=reg>>8;
    msg[num++]=reg&0xFF;
    msg[num++]=value>>8;
    msg[num++]=value&0xFF;
    uint16_t crc_sum = modbus_crc16(msg,num);
    msg[num++] = crc_sum & 0xFF;
    msg[num++] = crc_sum >> 8;
    memcpy(outmsg,msg,num);
    return EMU_SUCCESS;
}

//0x20
int emupacket_load_start_frame(uint8_t filetype,uint32_t filesize,uint16_t packsize,uint8_t*outmsg)
{
    unsigned char msg[MGS_LEN_MAX];
    int num = 0;
    memset(msg,0,MGS_LEN_MAX);
    msg[num++]=0x68;
    msg[num++]=0;
    msg[num++]=0x01;
    msg[num++]=FC_LOAD_STARTFRAME;
    msg[num++]=filetype;
    msg[num++]= filesize >>24;
    msg[num++]= (filesize >>16)& 0xFF;
    msg[num++]= (filesize >>8)& 0xFF;
    msg[num++]= filesize & 0xFF;
    msg[num++]=packsize>>8;
    msg[num++]=packsize&0xFF;
    uint16_t crc_sum = modbus_crc16(msg,num);
    msg[num++] = crc_sum & 0xFF;
    msg[num++] = crc_sum >> 8;
    memcpy(outmsg,msg,num);
    return EMU_SUCCESS;
}

//0x21
int emupacket_load_data_frame(uint8_t filetype,uint16_t packet_num,uint8_t*data,int len,uint8_t*outmsg)
{
    unsigned char msg[MGS_LEN_MAX];
    int num = 0;
    memset(msg,0,MGS_LEN_MAX);
    msg[num++]=0x68;
    msg[num++]=0;
    msg[num++]=0x01;
    msg[num++]=FC_LOAD_DATAFRAME;
    msg[num++]=filetype;
    msg[num++]=packet_num>>8;
    msg[num++]=packet_num&0xFF;
    memcpy(msg+num,data,len);
    num+=len;
    uint16_t crc_sum = modbus_crc16(msg,num);
    msg[num++] = crc_sum & 0xFF;
    msg[num++] = crc_sum >> 8;
    memcpy(outmsg,msg,num);
    return EMU_SUCCESS;
}

//0x22
int emupacket_load_end_frame(uint8_t filetype,uint8_t*outmsg)
{
    unsigned char msg[MGS_LEN_MAX];
    int num = 0;
    memset(msg,0,MGS_LEN_MAX);
    msg[num++]=0x68;
    msg[num++]=0;
    msg[num++]=0x01;
    msg[num++]=FC_LOAD_ENDFRAME;
    msg[num++]=filetype;
    uint16_t crc_sum = modbus_crc16(msg,num);
    msg[num++] = crc_sum & 0xFF;
    msg[num++] = crc_sum >> 8;
    memcpy(outmsg,msg,num);
    return EMU_SUCCESS;
}

//0x24
int emupacket_read_error_file(uint8_t filenum,uint16_t packet_num,uint8_t*outmsg)
{
    unsigned char msg[MGS_LEN_MAX];
    int num = 0;
    memset(msg,0,MGS_LEN_MAX);
    msg[num++]=0x68;
    msg[num++]=0;
    msg[num++]=0x01;
    msg[num++]=FC_READ_ERRORFILE;
    msg[num++]=filenum;
    msg[num++]=packet_num>>8;
    msg[num++]=packet_num&0xFF;
    uint16_t crc_sum = modbus_crc16(msg,num);
    msg[num++] = crc_sum & 0xFF;
    msg[num++] = crc_sum >> 8;
    memcpy(outmsg,msg,num);
    return EMU_SUCCESS;
}

//0x27
int emupacket_read_reg1_frame(uint8_t group,uint8_t*outmsg)
{
    unsigned char msg[MGS_LEN_MAX];
    int num = 0;
    memset(msg,0,MGS_LEN_MAX);
    msg[num++]=0x68;
    msg[num++]=0;
    msg[num++]=0x01;
    msg[num++]=FC_READ_REG1_FRAME;
    msg[num++]=group;

    uint16_t crc_sum = modbus_crc16(msg,num);
    msg[num++] = crc_sum & 0xFF;
    msg[num++] = crc_sum >> 8;
    memcpy(outmsg,msg,num);
    return EMU_SUCCESS;
}

//0x28
int emupacket_read_reg2_frame(uint8_t*outmsg)
{
    unsigned char msg[MGS_LEN_MAX];
    int num = 0;
    memset(msg,0,MGS_LEN_MAX);
    msg[num++]=0x68;
    msg[num++]=0;
    msg[num++]=0x01;
    msg[num++]=FC_READ_REG2_FRAME;
    uint16_t crc_sum = modbus_crc16(msg,num);
    msg[num++] = crc_sum & 0xFF;
    msg[num++] = crc_sum >> 8;
    memcpy(outmsg,msg,num);
    return EMU_SUCCESS;
}

//0x30
int emupacket_read_reg30_frame(uint8_t*outmsg)
{
    unsigned char msg[MGS_LEN_MAX];
    int num = 0;
    memset(msg,0,MGS_LEN_MAX);
    msg[num++]=0x68;
    msg[num++]=0;
    msg[num++]=0x01;
    msg[num++]=FC_READ_REG2_FRAME;
    uint16_t crc_sum = modbus_crc16(msg,num);
    msg[num++] = crc_sum & 0xFF;
    msg[num++] = crc_sum >> 8;
    memcpy(outmsg,msg,num);
    return EMU_SUCCESS;
}

//0x25
int emupacket_read_osc_file(uint8_t filesn,uint8_t*outmsg)
{
    unsigned char msg[MGS_LEN_MAX];
    int num = 0;
    memset(msg,0,MGS_LEN_MAX);
    msg[num++]=0x68;
    msg[num++]=0;
    msg[num++]=0x01;
    msg[num++]=FC_READ_OSC_FILE;
    msg[num++]=filesn;

    uint16_t crc_sum = modbus_crc16(msg,num);
    msg[num++] = crc_sum & 0xFF;
    msg[num++] = crc_sum >> 8;
    memcpy(outmsg,msg,num);
    return EMU_SUCCESS;
}

rt_uint16_t get_plcIdx()
{
    static rt_uint16_t idx=0x0000;
    return idx++;
}

int emupack_plc_baisc(uint16_t fcode,uint8_t*outmsg)
{
     outmsg[0]=0x48;
     outmsg[1]=0x40;
     outmsg[2]=fcode & 0xFF;
     outmsg[3]=fcode >>8;
     outmsg[4]=get_plcIdx()& 0xFF;
     outmsg[5]=get_plcIdx()>>8;
     return 6;
}
int empack_crc(uint8_t*outmsg,uint32_t len)
{
    uint16_t crc_sum = modbus_crc16(outmsg,len);
    outmsg[len++] = crc_sum & 0xFF;
    outmsg[len++] = crc_sum >> 8;
    return len;
}
int emupack_plc_readDevice(uint8_t*outmsg)
{
      unsigned char msg[MGS_LEN_MAX];
      int num = 0;
      memset(msg,0,MGS_LEN_MAX);
      msg[num++]=0x48;
      msg[num++]=0x40;
      msg[num++]=0x21;
      msg[num++]=0x00;
      msg[num++]=get_plcIdx()& 0xFF;
      msg[num++]=get_plcIdx()>>8;
      //长度
      rt_uint8_t len_index = num;
      num+=2;

      uint16_t crc_sum = modbus_crc16(msg,num);
      msg[num++] = crc_sum & 0xFF;
      msg[num++] = crc_sum >> 8;
      memcpy(outmsg,msg,num);
      return num;
}



void    wn_update_field_addr(wn_device_t* device,rt_uint32_t addr,rt_uint32_t value)
{
    switch(addr)
    {
        case 1: //额定输出电压
        case 1+(1*4)://额定输出电流
        case 1+(2*4)://额定输出功率
        case 1+(3*4)://额定频率
            break;
        case 1+(4*4):
        {
            //PV瞬时功率
            device->param_data.pvTempPower = value;
        }
        break;
        case 1+(5*4):
        {
            //AC瞬时功率
            device->param_data.acTempPower = value;
        }
        break;
        case 1+(6*4):
        {
            //电网频率
            device->param_data.gridFreq = value;
        }
        break;
        case 1+(7*4):
        {
            //启动控制
            device->param_data.sysctlCmd = value;
        }
        break;
        case 1+(8*4):
        {
            //系统状态
            device->param_data.sysStatus = value;
        }
        break;
        case 110:
        {
            //PV电压1实际值
            device->param_data.pvVolReal = value;
        }
        break;
        case 114:
        {
            //PV电流1实际值
            device->param_data.PvCurrReal = value;
        }
        break;
        case 118:
        {
            //PV电压1实际值
            device->param_data.acVolReal = value;
        }
        break;
        case 122:
        {
            //AC电流1实际值
            device->param_data.acVolReal = value;
        }
        break;
        case 126:
        {
            //PV电压1实际值
            //device->param_data.pvVolReal = value;
        }
        break;
        case 130:
        {
            //AC MOS 温度实际值
            device->param_data.acMosTempReal = value;
        }
        break;
        case 134:
        {
            //PV MOS 温度实际值
            device->param_data.pVMosTempReal = value;
        }
        break;
    }
}

rt_uint8_t wn_plc_readDevice()
{
    char outdata[256];
    int datalen = emupack_plc_readDevice(outdata);
    serial_send(&g_wn_serial, outdata, datalen);
    //等结果，解析，更新
    rt_uint32_t recved;
   // rt_uint8_t ret = rt_event_recv(plc_event, PLC_READDEVICE_RESP_EVENT, RT_EVENT_FLAG_OR, 5, recved);
    return 0;

}
rt_uint8_t wn_plc_readMac()
{
    char outdata[256];
    int datalen = emupack_plc_baisc(FC_READ_PLC_MACADDRESS,outdata);
    outdata[datalen++]=0x00;
    outdata[datalen++]=0x00;
    datalen = empack_crc(outdata,datalen);
    serial_send(&g_wn_serial, outdata, datalen);
    return 0;
}
rt_uint8_t wn_plc_readVersion()
{
    char outdata[256];
    int datalen = emupack_plc_baisc(FC_READ_PLC_VERSION,outdata);
    outdata[datalen++]=0x00;
    outdata[datalen++]=0x00;
    datalen = empack_crc(outdata,datalen);
    serial_send(&g_wn_serial, outdata, datalen);
    return 0;
}
rt_uint8_t wn_plc_readWhiteListNum()
{
    char outdata[256];
    int datalen = emupack_plc_baisc(FC_READ_PLC_WHITELISTNUM,outdata);
    outdata[datalen++]=0x00;
    outdata[datalen++]=0x00;
    datalen = empack_crc(outdata,datalen);
    serial_send(&g_wn_serial, outdata, datalen);
    return 0;
}
rt_uint8_t wn_plc_readWhiteListInfo()
{
    char outdata[256];
    int datalen = emupack_plc_baisc(FC_READ_PLC_WHITELISTINFO,outdata);
    outdata[datalen++]=0x00;
    outdata[datalen++]=0x00;
    datalen = empack_crc(outdata,datalen);
    serial_send(&g_wn_serial, outdata, datalen);
    return 0;
}
rt_uint8_t wn_plc_addWhiteList(rt_uint8_t* deviceData,rt_uint16_t deviceNum)
{
    char outdata[256];
    int datalen = emupack_plc_baisc(FC_ADD_PLC_WHITELIST,outdata);
    rt_uint16_t totalLen = 6*deviceNum+2;
    outdata[datalen++] = totalLen & 0xFF;
    outdata[datalen++] = totalLen >> 8;
    outdata[datalen++] = deviceNum & 0xFF;
    outdata[datalen++] = deviceNum >> 8;
    for(int i=0;i<totalLen;i++)
    {
        outdata[datalen++]=deviceData[i];
    }
    datalen = empack_crc(outdata,datalen);
    serial_send(&g_wn_serial, outdata, datalen);
    return 0;
}
rt_uint8_t wn_plc_delWhiteList(rt_uint8_t* deviceData,rt_uint16_t deviceNum)
{
    char outdata[256];
    int datalen = emupack_plc_baisc(FC_DEL_PLC_WHITELIST,outdata);
    rt_uint16_t totalLen = 6*deviceNum+2;
    outdata[datalen++] = totalLen & 0xFF;
    outdata[datalen++] = totalLen >> 8;
    outdata[datalen++] = deviceNum & 0xFF;
    outdata[datalen++] = deviceNum >> 8;
    for(int i=0;i<totalLen;i++)
    {
        outdata[datalen++]=deviceData[i];
    }
    datalen = empack_crc(outdata,datalen);
    serial_send(&g_wn_serial, outdata, datalen);
    return 0;
}

rt_uint8_t wn_plc_readNetNodes(rt_uint16_t* startnode,rt_uint16_t nodeNum)
{
    char outdata[256];
    int datalen = emupack_plc_baisc(FC_DEL_PLC_WHITELIST,outdata);
    rt_uint16_t totalLen = 0x0004;
    outdata[datalen++] = totalLen & 0xFF;
    outdata[datalen++] = totalLen >> 8;
    outdata[datalen++] = *startnode & 0xFF;
    outdata[datalen++] = *startnode >> 8;
    outdata[datalen++] = nodeNum & 0xFF;
    outdata[datalen++] = nodeNum >> 8;
    datalen = empack_crc(outdata,datalen);
    serial_send(&g_wn_serial, outdata, datalen);
    return 0;
}

rt_uint8_t wn_plc_transform(rt_uint32_t* address,rt_uint8_t* wnData,rt_uint16_t wnDataLen)
{
    char outdata[256];
    int datalen = emupack_plc_baisc(FC_PLC_TRANSFORM,outdata);
    rt_uint16_t totalLen = 6+2+wnDataLen;
    outdata[datalen++] = totalLen & 0xFF;
    outdata[datalen++] = totalLen >> 8;
    outdata[datalen++] = *address & 0xFF;
    outdata[datalen++] = (*address >> 8) & 0xFF;
    outdata[datalen++] = (*address >> 16) & 0xFF;
    outdata[datalen++] = (*address >> 24) & 0xFF;
    outdata[datalen++] = 0;
    outdata[datalen++] = 0;
    outdata[datalen++] = wnDataLen & 0xFF;
    outdata[datalen++] = wnDataLen >> 8;
    for(int i = 0;i<wnDataLen;i++)
    {
        outdata[datalen++] = wnData[i];
    }
    datalen = empack_crc(outdata,datalen);
    serial_send(&g_wn_serial, outdata, datalen);
    return 0;
    //阻塞读取
//    uint8_t recvData[1024];
//    int recvlen = recv_onepacket(g_wn_serial,recvData,1024,300,0,NULL);
//    if(recvlen == -1)
//    {
//        printf("超时");
//    }
//    handle_wn_reveivedata(recvData, recvlen);
}
